using System;
using System.IO;
using System.IO.Ports;
using System.Threading;
using System.Threading.Tasks;

namespace IntegratedMeasuring.Utils
{
    /// <summary>
    /// PLC通信辅助类，支持定时读取和数据变化事件发布
    /// </summary>
    public class PLCCommunicationHelper : IDisposable
    {
        private SerialPort? _serialPort;
        private string _lastValidValue = "";
        private Task? _monitoringTask;
        private CancellationTokenSource? _cancellationTokenSource;
        private readonly object _lockObject = new();
        //40 30 30 52 44 30 39 32 38 30 30 30 34 35 31 2A 0D 
        //40,30,30,52,44,30,39,32,38, 30, 30, 34, 35, 31, 2A, 0D
        private readonly byte[] sendMsg = new byte[] { 0x40, 0x30, 0x30, 0x52, 0x44, 0x30, 0x39, 0x32, 0x38, 0x30, 0x30,0x30, 0x34, 0x35, 0x31, 0x2A, 0x0D };

        public event EventHandler<PLCDataChangedEventArgs>? DataChanged;

        /// <summary>
        /// 打开PLC串口连接，并启动定时读取
        /// </summary>
        /// <returns>连接成功返回true，否则false</returns>
        public bool OpenConnection(out string? errorMsg)
        {
            var (portName, baudRate) = ReadConfig();
            try
            {
                _serialPort = new SerialPort(portName, baudRate, Parity.None, 8, StopBits.One)
                {
                    ReadTimeout = 1000,
                    WriteTimeout = 1000
                };
                _serialPort.Open();
                StartMonitoring();
                errorMsg = string.Empty;
                return true;
            }
            catch (Exception ex)
            {
                errorMsg = ex.Message;
                _serialPort = null;
                return false;
            }
        }

        /// <summary>
        /// 关闭连接和监控
        /// </summary>
        public void CloseConnection()
        {
            StopMonitoring();
            if (_serialPort != null)
            {
                try { _serialPort.Close(); } catch { }
                _serialPort.Dispose();
                _serialPort = null;
            }
        }

        /// <summary>
        /// 读取配置文件，返回串口号和波特率
        /// </summary>
        private (string, int) ReadConfig()
        {
            string defaultPort = "COM9";
            int defaultBaudRate = 19200;
            string configPath = Path.Combine(AppContext.BaseDirectory, "plc.data");
            try
            {
                if (File.Exists(configPath))
                {
                    var line = File.ReadAllText(configPath).Trim();
                    if (!string.IsNullOrEmpty(line))
                    {
                        var parts = line.Split(':');
                        if (parts.Length == 2 && int.TryParse(parts[1], out int baudRate))
                        {
                            string portName = parts[0];
                            return (portName, baudRate);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"读取PLC配置文件出错: {ex.Message}");
            }
            return (defaultPort, defaultBaudRate);
        }

        /// <summary>
        /// 启动PLC数据监控任务
        /// </summary>
        private void StartMonitoring()
        {
            _cancellationTokenSource = new CancellationTokenSource();
            
            var token = _cancellationTokenSource.Token;
            token.Register(() =>
            {
                _monitoringTask?.Dispose();
                _monitoringTask = null;
            } );
            _monitoringTask = Task.Run(async () =>
            {
                while (!token.IsCancellationRequested)
                {
                    try
                    {
                        // _serialPort?.WriteLine( "@00RD0928000451*\n");
                        // _serialPort.DtrEnable = true;
                        _serialPort.Parity= Parity.Even;
                        // _serialPort.RtsEnable = true;
                        _serialPort?.Write(sendMsg, 0, sendMsg.Length);
                        await Task.Delay(500, token);
                     //   Console.WriteLine($"HUSSFSDFA: {_serialPort.BytesToRead}");
                        string? response = _serialPort?.ReadExisting();
                        System.Console.WriteLine($"PLC响应: {response}");
                        if (!string.IsNullOrEmpty(response))
                        {
                            if (response.StartsWith("@00RD00") && response.EndsWith("*\r"))
                            {
                                lock (_lockObject)
                                {
                                    if (_lastValidValue == "")
                                    {
                                        _lastValidValue = response;
                                    }
                                    else if (_lastValidValue != response)
                                    {
                                        _lastValidValue = response;
                                        DataChanged?.Invoke(this, new PLCDataChangedEventArgs(response));
                                    }
                                }
                            }
                        }
                    }
                    catch (TimeoutException)
                    {
                        // 忽略超时
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Debug.WriteLine($"PLC读取异常: {ex.Message}");
                    }
                    await Task.Delay(1000, token);
                }
            }, token);
        }

        /// <summary>
        /// 停止PLC数据监控任务
        /// </summary>
        private void StopMonitoring()
        {
            if (_cancellationTokenSource != null)
            {
                _cancellationTokenSource.Cancel();
                _monitoringTask?.Wait(500);
                _cancellationTokenSource.Dispose();
                _cancellationTokenSource = null;
            }
        }

        public void Dispose()
        {
            CloseConnection();
        }
    }

    /// <summary>
    /// PLC数据变化事件参数
    /// </summary>
    public class PLCDataChangedEventArgs : EventArgs
    {
        public string NewValue { get; }
        public PLCDataChangedEventArgs(string newValue)
        {
            NewValue = newValue;
        }
    }
} 